import express = require('express')
const router = express.Router()

interface pointer {
  x: number;
  y: number;
}

interface pointer2 extends pointer {
  z: number
}

interface Db {
  host: string;
  port: number;

  connect(password: string, username: string): void;
}

enum Choose {
  wife,
  mather
}

type Address = string
type Tel = number

class MySql implements Db {
  readonly host: string = "initValue"; // 只能是可读, not change, first set initial value
  port: number;
  constructor() {
    this.host = '9999' // readonly property can be constructor  change.
  }

  connect(pwd: string, uname: string): void { }
}

let server = new MySql()
console.log(server.host)


function question(choose: Choose): Number {
  console.log(`你媳妇和你母亲同时掉进水里你先救哪个?`);
  console.log(`i will rescue + ${choose}`);
  return choose
}

function somefunc({ x = 0, y = 0, z = 3 }: pointer2 = { x: 2, y: 2, z: 8 }) {
  console.log(z);
}

class Person {
  name: string;
  age: number;
  labels: Array<string>;
  wives: string[];
  contact: [Address, Tel];
  other: any;
  saveMonth: boolean = true;
  constructor() { }
  answer(): Choose {
    if (this.saveMonth === false) {
      return Choose.wife
    }
    return Choose.mather
  }
  hello(): void {
    console.log(`hello i am + ${this.name}`);
  }
  emty() { }
  down(): never {
    // 死循环
    while (true) { }
  }
}

interface OrProperty {
  readonly IdCard: string;
  name?: string;
  [index: string]: any;
}

let PropertyObj: OrProperty = {
  IdCard: '99999',
  0: 20,
  age: ["false", 'ssss']
}

// 接口描述函数
type DB = string;

interface InitFunc {
  (options: DB): string
}

let MyFunc: InitFunc = (options: DB) => {
  console.log(options)
  return '';
}

MyFunc(`描述接口函数加载完成...`)

// 描述可实例化
interface MyDateInit {
  new(year: string, month: string, day: string): MyDate;
}

interface MyDate {
  year: string;
  month: string;
  day: string;
}

class MyDateClass implements MyDate {
  year: string;
  month: string;
  day: string;
  constructor(year: string, month: string, day: string) {
    this.year = year;
    this.month = month;
    this.day = day;
    console.log('描述可实例化代码完成...')
    return this;
  }
}

function getDate(Class: MyDateInit, { year, month, day }): MyDate {
  return new Class(year, month, day)
}

getDate(MyDateClass, { year: '2018', month: '12', day: '1' })

// 描述混合类型
interface Counter {
  (start: number): string;
  interval: number;
  reset(): void;
}

function getCounter(): Counter {
  let counter = <Counter>function (start: number) { console.log('start is ' + start) }
  counter.interval = 123
  counter.reset = () => console.log('reset is finish.')
  return counter
}

let c = getCounter();
c(10)
c.reset()
c.interval = 11

// 函数声明
interface AddFunc {
  (x: number, y: number): number
}

let Add1: AddFunc
Add1 = function add2(x: number, y: number): number {
  return x + y
}

// 不用interface
let Add3: (x: number, y: number) => number = function (x, y) {
  return x + y
}

// 可选和默认值
let add10 = function (x: number, ...y) {
  console.log(x)
}

add10(1, 2, 3, 45, 6, 7)

const arr = [1, 23, 4]
const arr2 = [...arr, 33, 55]
const arr3 = [33, 55, ...arr]

// 泛型
let one2: <T>(a: T[]) => T = a => a[0];
one2([1, 2, 3, 'sss'])
// 接口泛型
interface some<T> {
  (a: T[]): T
}

let one3: some<number> = function (a) {
  return a[0]
}

one3([1, 2, 3])

// 类泛型
class ClassPerson<T, U> {
  other: T
  age: U
}

let cp = new ClassPerson<string, number>()

// 泛型继承
interface hasLength {
  length: number
}

function funcTest<T extends hasLength>(params: T): T {
  return params
}

funcTest([1, 2, 3, 4])

// 原型

// new 
// type
let tBoolean: boolean = true;
let tNumber: number = 3;
let tString: string = 'second';
let tStingES6: string = `good man ${tString}`
let tList: number[] = [1, 2, 3];
let tListArray: Array<number> = [1, 3, 3, 4]
let tListArrayOther: [number, string, object] = [1, "2", { a: 3 }]
enum color {
  Red,
  Green,
  Blue
}
let colorChoose: color = color.Red;

let tAny: any = 4;
tAny = '现在变成字符串了呦.'
console.log(tAny);

let tScoreRow: any[] = [100, 'aaaa', 20]

function voidFunc(): void {
  console.log('该函数没有返回值... 该函数类型为void')
}
voidFunc();

var tSomeVal: any = `0002151651561651`;
let tValLength: number = (<string>tSomeVal).length;
let tValLengthAs: number = (tSomeVal as string).length;
console.log(tValLengthAs)

// interface

interface monther {
  name: string;
  age: number;
}
function boy(opts: monther) {
  console.log(`this boy name is ${opts.name}, age is ${opts.age}`)
}

let boyProperty = { name: 'good man', age: 22 }
boy(boyProperty);

interface someRepeat {
  (initText: string, findText: string): boolean
}

let findFunc: someRepeat;
findFunc = function (s: string, f: string) {
  var _res = s.search(f);
  if (_res !== -1) {
    return true
  } else {
    return false
  }
}
console.log(findFunc('helloworld', 'ld'))

interface stringArray {
  [index: number]: string
}

let testArray: stringArray;

// 类接口
interface ClockInterface {
  currentTime: Date;
  setTime(d: Date);
}

class Clock implements ClockInterface {
  currentTime: Date;
  setTime(d: Date) {
    this.currentTime = d;
  }
  constructor(h: number, m: number) {

  }
}

let clock = new Clock(16, 25);

// interface extends
interface mather {
  name: string;
  age: number;
}

interface father extends mather {
  height: number;
}

let familyProperty = <father>{};
familyProperty.name = 'xiaoming'
familyProperty.height = 199
familyProperty.age = 22
console.log(familyProperty)

// class && class extends
// public 公共的
// private 私有的
// protected 受保护的
// static 静态的
// abstract
class Family {
  father: string;
  mather: string;
  son(age: number) {
    console.log(`-> i am ${this.father} son. i am ${age} years old.`)
  }

  constructor(fName: string, mName?: string) {
    this.father = fName;
    this.mather = mName;
  }
}

class Son extends Family {
  age: number;
  constructor(fName: string, age: number) {
    super(fName)
    this.age = age;
  }
  hi(age = this.age) {
    this.son(age)
  }
}

let family = new Family('F', 'M');
let sonFamily = new Son('F', 18);
console.log(family.father, family.mather, family.son)
sonFamily.hi();

// func
function tFunc(x: number, y: number): number {
  return x + y;
}
console.log(tFunc(10, 22));

let tFunc2: (x: number, y: number) => number = (x: number, y: number) => {
  return x + y;
}
console.log(tFunc2(10, 55))

function school(student: string, ...otherStudents: string[]) {
  console.log(`老同学: ` + student, `其他同学: ` + otherStudents.join(' '))
}
school('aa', 'bbb', 'ddd', 'cccc')

// genericity
function why<X>(chr: X): X {
  return chr
}
console.log(why<string>('string genericity'));

function whyGenericityArray<T>(a: T[]): T {
  return a[0];
}

let genericity2: <T>(a: T[]) => T = a => { console.log(`当前数组第一项为` + a[0]); return a[0] };
genericity2([11, 1])


function createArray<T>(length: number, value: T): Array<T> {
  let result: T[] = [];
  for (let i = 0; i < length; i++) {
    result[i] = value;
  }
  return result;
}
let resArray = createArray(3, 'yyy');
console.log(resArray)

// more type genericity
function createMoreType<T, U>(tuple: [T, U]): U {
  let tu1 = tuple[1];
  let tu2 = tuple[0];
  return tu1
}
let resArrayMore = createMoreType([7, 'seven']);
console.log(resArrayMore)

function createOneType<T>(tuple: T): T {
  let tu1 = tuple[1];
  let tu2 = tuple[0];
  return tu1 + tu2
}
let restArray3 = createOneType([2222, 'seven']);
console.log(restArray3)


// interface genericity 申明的时候就要规定格式
interface generInterface<T> {
  (arg: T): T
}

interface generInterfaceTwo {
  <T>(arg: T): T
}

interface genericityThree<T,U> {
  (a: T[]): U
}

let threeFunc: genericityThree<number, number> = function(a) {
  return a[0]
}


let generInterfaceTwo: generInterfaceTwo = function (a) {
  return a[0]
}
console.log(generInterfaceTwo([11,22,33]));

interface extednsGenerInterface {
  length: number;
}

function whyGenericity<T>(chr: T): T {
  console.log(typeof chr)
  return chr;
}

function whyGenericityTwo<T extends extednsGenerInterface>(chr: T): T {
  console.log(chr.length, '传过来的长度.');
  return chr;
}
let num: generInterface<number> = whyGenericity;
console.log(num(10))
console.log(whyGenericityTwo("999999"))

// enum
enum familyAge {
  father = 33,
  mather = 22,
  son = 10,
  daughter = 11,
  fatherNameLength = 'xiaoming'.length
}

console.log(familyAge[familyAge.father] + ' age is ' + familyAge.father)

let max: number = 3;
let test: number = 5;
if (test !== max) {
  console.log('不知道.')
}

// example class genericity extends
class BeeKeeper {
  hasMask: boolean
}

class ZooKeeper {
  nametag: string
}

class Animal {
  numLength: number
}

class Bee extends Animal {
  keeper: BeeKeeper
}

class Lion extends Animal {
  keeper: ZooKeeper
}

function findKeeper<A extends Animal, K> (
  a: {
    new (): A;
    prototype: {
      keeper: K
    }
  }
):K {
  return a.prototype.keeper
}

let keeper = findKeeper(Lion);









router.get('/', (req: any, res: any) => {
  let privatePer = new Person()
  privatePer.name = 'djkloop'
  privatePer.age = 23
  privatePer.labels = ['叼的不行', '颜值逆天', '年轻多金']
  privatePer.wives = ['-', '==', '---']
  privatePer.contact = ['北京别墅', 2]
  privatePer.saveMonth = false
  privatePer.other = '牛逼的人'
  privatePer.hello()
  question(privatePer.answer())
  somefunc()
  let otherLen = (privatePer.other as string).length
  console.log(otherLen)

  res.status(200).json({
    message: '后台代码加载成功...'
  })
})

module.exports = router;
